import 'dart:async';
import 'dart:convert';

// import 'dart:convert' as convert;
import 'dart:io';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:device_info/device_info.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:jpush_flutter/jpush_flutter.dart';

// import 'package:jpush_flutter/jpush_interface.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter_syt/api/EncryptUtils.dart';

import 'package:flutter_syt/api/api.dart';
import 'package:flutter_syt/channel_apis.dart';
import 'package:flutter_syt/datas/user_info.dart';
import 'package:flutter_syt/generated/l10n.dart';
import 'package:flutter_syt/global_common.dart';
import 'package:flutter_syt/routes.all.dart';
import 'package:flutter_syt/utils/utils_dlog.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:yyy_route_annotation/yyy_route_annotation.dart';

import 'domain/login/user_processor.dart';
import 'domain/waystation/map_processor.dart';
import 'global_easy_loading.dart';
import 'root_widget.dart';
import 'starter/app_context.dart';
import 'starter/env_provider.dart';
import 'starter/i18n/localeization_processor.dart';
import 'starter/platform/platform_processor.dart';
import 'starter/registry.dart';
import 'starter/storage/kv_storage_processor.dart';

AppContext? _appContext;

AppContext get appContext => _appContext!;

class Application extends AppContext {
  static final Application _instance = Application._();

  factory Application() => _instance;

  Application._();

  // final JPushFlutterInterface jPush = JPush.newJPush();
  final JPush jPush = JPush();

  void configLoading() {
    // jpush.setAuth();
    EasyLoading.instance
      ..displayDuration = const Duration(milliseconds: 2000)
      ..indicatorType = EasyLoadingIndicatorType.fadingCircle
      ..loadingStyle = EasyLoadingStyle.light
      ..indicatorSize = 45.0
      ..radius = 10.0
      ..progressColor = Colors.yellow
      ..backgroundColor = Colors.green
      ..indicatorColor = Colors.yellow
      ..textColor = Colors.yellow
      ..maskColor = Colors.blue.withOpacity(0.5)
      ..userInteractions = true
      ..fontSize = 16.0
      ..dismissOnTap = false;
  }

  // static StreamSubscription<dynamic> _clientSubscription;

  static Future configPush() async {
    return;
    if (Platform.isAndroid) {
      const EventChannel('PushApi/registerId')
          .receiveBroadcastStream()
          .listen((token) {
        print('tokenregisterId $token');
        //OnePlus_CN_ae8a60353b15369d18077243b1e18c52
        if (token['token'] != null) {
          GlobalData.setDevicTokenID(token['token']);
        } else if (token['jump_target'] != null) {
          Map map = token;
          if ((map).keys.contains('url')) {
            String url = map['url'];
            map['url'] = url.replaceAll("\\", '');
          }
          // EasyLoading.showToast('11111111111');
          JPushJump.excutePush(map.cast<String, dynamic>());
        }
        // else if (token['androidId'] != null) {
        //   // appContext.deviceId = token['androidId'];
        //   API.shared.common.startUpStatistics(token['androidId']);
        // }
      });
    }
    // else {
    //   // appContext.deviceId = appContext.iOSInfo.identifierForVendor;
    //   API.shared.common
    //       .startUpStatistics(appContext.iOSInfo.identifierForVendor);
    // }
    // final JPushFlutterInterface jPush = JPush.newJPush();
    JPush jPush = Application().jPush;
    // jPush.setAuth()
    appContext.channelApi.listen('PushApi/receiveMessage', (args) {
      // EasyLoading.showToast('222222222');
      JPushJump.excutePush(jsonEncode(args) as Map<String, dynamic>);
    });
    // _jPush.show
    // _jPush.setUnShowAtTheForeground(unShow: true);
    // JPush;
    jPush.addEventHandler(
      onReceiveMessage: (message) async {
        print('-------jpush onReceiveMessage-------$message');
        // OnlineGlobalData.shared.update();
      },
      onOpenNotification: (Map<String, dynamic> message) async {
        print('-------jpush onOpenNotification-------$message');
        Map<String, dynamic>? extraMap;
        if (Platform.isAndroid) {
          try {
            // print(jsonDecode(message['extras']['cn.jpush.android.EXTRA']));
            Map<String, dynamic>? mape =
                jsonDecode(message['extras']['cn.jpush.android.EXTRA']);
            extraMap = mape?.cast<String, String>();
            if ((extraMap ?? {}).keys.contains('url')) {
              String url = extraMap!['url'];
              extraMap['url'] = url.replaceAll("\\", '');
              // extraMap['url'] = url;
              print(url);
            }
          } catch (e) {}
        } else {
          extraMap = Map<String, dynamic>.from(
              message['extras']); //  message['extras'];
        }
        print(extraMap);
        // var ext = message['extras'] as Map<String, dynamic>;
        if (extraMap != null && extraMap.isNotEmpty) {
          // EasyLoading.showToast('333333333');
          JPushJump.excutePush(extraMap);
        }
      },
      onReceiveNotification: (Map<String, dynamic> message) async {
        print('-------jpush onReceiveNotification-------$message');
        // var localNotification = LocalNotification(
        //     id: 234,
        //     title: message['title'],
        //     buildId: 1,
        //     content: message['alert'],
        //     fireTime: DateTime.now(),
        //     subtitle: '',
        //     badge: 5,
        //     extra: {"fa": "0"});
        // _jPush.sendLocalNotification(localNotification);
      },
      onNotifyMessageUnShow: (event) async {
        print('------- onNotifyMessageUnShow-------$event');
      },
    );
    jPush.setup(
        appKey: "be2161b4eb3284ee2e89c728",
        channel: "main",
        production: false,
        debug: false);
    jPush.setAuth(enable: true);

    jPush.getRegistrationID().then((value) {
      GlobalData.setRegistrationID(value);
      DLog('getRegistrationID   $value');
      // return API.shared.user.setAlias(value);
    });
    jPush.setBadge(0);
    jPush.applyPushAuthority(
        NotificationSettingsIOS(sound: true, alert: true, badge: true));
  }

  void run(Type envType) async {
    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);

    jPush.setAuth(enable: false);

    _appContext = this;
    initPreInitConfig(this);
    // JPush.newJPush().setAuth(enable: false);

    // 创建上下文对象
    // 初始化环境注册信息 & 初始化启动处理器注册信息
    for (Registry registry in registry) {
      if (registry is ProcessorRegistry) {
        var all = registry.getAll();
        for (Type eachType in all) {
          await registry.getByType(eachType).postProcessor(this, envType);
        }
      }
    }

    if (appContext.provider.isDebug) {
      var cer = await rootBundle.load('assets/videos/devCER.pem');

      appContext.setCerBytes(cer.buffer.asUint8List());
    } else if (appContext.provider.isProd) {
      var cer = await rootBundle.load('assets/videos/cer.pem');

      appContext.setCerBytes(cer.buffer.asUint8List());
    } else if (appContext.provider.isQa) {
      var cer = await rootBundle.load('assets/videos/preCER.pem');

      appContext.setCerBytes(cer.buffer.asUint8List());
    }
    SystemChrome.setSystemUIOverlayStyle(CustomSystemUiOverlayStyle.dark);
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    // SystemUiOverlayStyle systemUiOverlayStyle =
    //     const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    // SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);

    runApp(AppRootWidget());
    configLoading();
  }

  Future initAppConfig() async {
    initConnectivity();
    // titleBarStyle();
    RouteManager.commonLoginInterceptor((context) async {
      if (!UserInfo.me.isLogin) {
        RouteManager.push(
          context,
          RoutMapping.loginByPwd(),
        );
      }
      return UserInfo.me.isLogin;
    });
    RouteManager.routeInterceptor((context, path) async {
      try {
        var uri = Uri.parse(path);
        var host = uri.host;
        if (host == "toast") {
          var parameters = uri.queryParameters;
          var message = parameters["message"] ?? "";
          if (message == '敬请期待') {
            var local = appContext.storage.getString("storyLocal") ??
                Intl.getCurrentLocale();
            if (local.contains('zh')) {
              customShowToast(message);
            } else {
              customShowToast(S().standy_by);
            }
          } else if (message.isNotEmpty) {
            customShowToast(message);
          }
          return false;
        } else if (host == 'native') {
          var parameters = uri.queryParameters;
          var page = parameters["page"] ?? "";
          if (page == 'translation') {
            // appContext.channelApi.openTransform();
          } else if (page == 'openAR') {
            customShowToast(S().standy_by);
            // appContext.channelApi.openAR();
          }
          return false;
        } else if (host == 'external') {
          var parameters = uri.queryParameters;
          var message = parameters["url"] ?? "";
          if (message.isNotEmpty && await canLaunchUrlString(message)) {
            launchUrlString(
              message,
              mode: LaunchMode.externalApplication,
            );
          }
          return false;
        }
      } catch (e) {}
      return true;
    });
    appContext.connectivitySubscription = appContext
        .connectivity.onConnectivityChanged
        .listen(_updateConnectionStatus);
  }

  static Future initDeviceInfo() async {
    var package = await PackageInfo.fromPlatform();
    appContext.setPackageInfo(package);
    await EncryptUtils.initRsa();
    if (Platform.isIOS) {
      var device = await DeviceInfoPlugin().iosInfo;
      appContext.setIOSInfo(device);
    } else {
      var device = await DeviceInfoPlugin().androidInfo;
      // var json = await appContext.channelApi.getAndroidId();
      DLog(json);
      // device.androidId = json['androidId'];
      appContext.setAndriodInfo(device);
    }
    try {
      API.shared.common.startUpStatistics(Platform.isIOS
          ? appContext.iOSInfo.identifierForVendor
          : appContext.andriodInfo.androidId);
    } catch (e) {}
  }

  static Future getTimeStamp() async {
    int count = await API.shared.common.getTimeStamp();

    appContext.timeStamp =
        (DateTime.now().millisecondsSinceEpoch ~/ 1000) - count;
  }

  Future<void> initConnectivity() async {
    late List<ConnectivityResult> results;
    try {
      results = await appContext.connectivity.checkConnectivity();
    } on PlatformException catch (e) {
      return;
    }
    appContext.connectionStatus = results.first;
  }

  Future<void> _updateConnectionStatus(List<ConnectivityResult> results) async {
    if (appContext.timeStamp == 0) {
      await getTimeStamp();
    }
    // Can lazy

    appContext.connectionStatus = results.first;
  }

  static Future lazyRegister() async {
    if (appContext.storage.getBool('isAgree')) {
      await initDeviceInfo();
      await Application().initAppConfig();

      await getTimeStamp();
      await configPush();
      // MapInitializedProcessor().postProcessor(appContext);
    }
    return;
  }

  // static void titleBarStyle() {
  //   // title bar https://www.jianshu.com/p/b931c05b0df9
  //   SystemUiOverlayStyle style = SystemUiOverlayStyle(
  //       statusBarColor: Colors.transparent,
  //       statusBarIconBrightness: Brightness.light,
  //       statusBarBrightness: Brightness.light);
  //   SystemChrome.setSystemUIOverlayStyle(style);
  // }

  static ProcessorRegistry processRegistry = ProcessorRegistry();

  void initPreInitConfig(AppContext appContext) {
    EnvProviderRegistry envRegistry = EnvProviderRegistry();
    envRegistry.register(EnvProductProvider, EnvProductProvider());
    envRegistry.register(EnvQAProvider, EnvQAProvider());
    envRegistry.register(EnvDevProvider, EnvDevProvider());

    processRegistry.register(EnvProcessor, EnvProcessor());
    processRegistry.register(KVStorageProcessor, KVStorageProcessor());
    processRegistry.register(NativeNavProcessor, NativeNavProcessor());
    processRegistry.register(LocalizationProcessor, LocalizationProcessor());
    processRegistry.register(SessionProcessor, SessionProcessor());

    // processRegistry.register(MapInitializedProcessor, MapInitializedProcessor());

    appContext.registry = [envRegistry, processRegistry];
  }
}
